//
// Created by QU on 2023/12/16.
//

// c++ 在11之前使用的auto_ptr存在缺陷, 后来c++提供了unique_ptr, shared_ptr, weak_ptr来解决这样的问题, auto_ptr也被声明为弃用.
// 在boost程序库中提供了smart_ptr系列指针, 你只需要包含<boost/smart_ptr.hpp>就可以使用boost提供的各种类型的指针了.

// cpp_standered
#include <iostream>
#include <string>

// boost_lib
#include <boost/smart_ptr.hpp>

using std::cout, std::cin, std::endl, std::string;


// 如果一个类持有了scoped_ptr成员变量, 那么这个类也是不可拷贝和赋值的.
class my_ptr_owned final {
    boost::scoped_ptr<int> int_ptr;
};

struct posix_file{
    string fname;

    posix_file(const char * filename) : fname(filename){
        cout << "open the file: " << filename << endl;
    };

    ~posix_file(){
        cout << "closed file" << endl;
    }

};


int main(int argc, char* argv[]){

    // scoped_ptr: 一旦scoped_ptr获得了对象的管理权,那么我们就无法从他哪里收回来.
    boost::scoped_ptr<std::string> sp(new std::string("this is scoped_ptr string builded text."));
    assert(sp);
    assert(sp != nullptr);
    
    cout << *sp << endl;
    cout << sp.get() << endl;

    // 这个其实有这样的, 可能不习惯. 能够调用sp中的内容
    cout << (*sp).size() << endl;
    cout << sp->size() << endl;
    
    // 从后面开始, 我们将省略boost
    using boost::scoped_ptr;

    // scoped_ptr<string> scop_ptr2 = sp;
    // 这样的是不行的, sp不能拷贝复制函数.

    scoped_ptr<posix_file> fp(new posix_file(R"(/home/local_user/xxxxx)"));
    // 大概意思是说这样在离开作用域的时候, scoped_ptr可以自己调用析构函数(包括posix_file类的析构)帮助我们释放资源.
    // 如果这个资源执行完, scoped_ptr将调用析构函数帮助我们释放这个文件.

    scoped_ptr<int> ip(new int);        // 这里存着是一个int类型的指针

    if (ip){
       *ip = 200;
       cout << "*ip is : " << *ip << endl;
    }

    ip.reset(); // p持有的指针清空
    // 这个时候ip指向的就是0(nullptr). 访问*ip的时候就会assert Failed;
    // assert(*ip);

    assert(ip == nullptr);
    if (ip) {
        cout << "scoped_ptr is nullptr!" << endl;
    }

    // unique_ptr的基本能力和scoped_ptr相同, c++标准库的unique_ptr的功能比scoped_ptr更强.
    using std::unique_ptr;
//    unique_ptr<T,D> T是保存数据的指针, D是可自定义的删除器
    unique_ptr<posix_file> uniquePtr(new posix_file(R"(c:\User\aquawius\target of love.mp3)"));

    if (uniquePtr){
        cout << "uniquePtr->fname is : " << uniquePtr->fname << endl;
    }

}
